﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using AdvplDoc.Model;
using AdvplDoc.View;

namespace AdvplDoc {

	public partial class MainWindow : Form {

		IniFile iniFile;

		public MainWindow() {
			InitializeComponent();

            this.iniFile = new IniFile();
			this.readIniFile();
		}

		private void readIniFile() {
			this.txtInputPath.Text = this.iniFile.ReadValue("input", "path");

			List<string> extensions = new List<string>(this.iniFile.ReadValue("input", "file_extensions").Split(' '));

			this.chkC.Checked = extensions.Contains(".c");
			this.chkH.Checked = extensions.Contains(".h");
			this.chkCPP.Checked = extensions.Contains(".cpp");
			this.chkHPP.Checked = extensions.Contains(".hpp");
			this.chkINL.Checked = extensions.Contains(".inl");

			this.txtOutputPath.Text = this.iniFile.ReadValue("output", "path");

			this.cmbOutputFormat.SelectedItem = this.iniFile.ReadValue("output", "format");
		}

		private void writeIniFile() {
			this.iniFile.WriteValue("input", "path", this.txtInputPath.Text);

			this.iniFile.WriteValue("input", "file_extensions", String.Join(" ", this.getExtensionList()));

			this.iniFile.WriteValue("output", "path", this.txtOutputPath.Text);

			this.iniFile.WriteValue("output", "format", (string)this.cmbOutputFormat.SelectedItem);
		}

		private List<string> getExtensionList() {
			List<string> extensions = new List<string>();

			if (this.chkC.Checked)
				extensions.Add(".c");

			if (this.chkH.Checked)
				extensions.Add(".h");

			if (this.chkCPP.Checked)
				extensions.Add(".cpp");

			if (this.chkHPP.Checked)
				extensions.Add(".hpp");

			if (this.chkINL.Checked)
				extensions.Add(".inl");

			return extensions;
		}
		
		private void button2_Click(object sender, EventArgs e) {
			FolderBrowserDialog folderBrowser = new FolderBrowserDialog();
			folderBrowser.ShowNewFolderButton = false;
			folderBrowser.Description = "Selecione o diretorio inicial";
			DialogResult result = folderBrowser.ShowDialog(this);

			if (result == System.Windows.Forms.DialogResult.OK) {
				this.txtInputPath.Text = folderBrowser.SelectedPath;				
				this.iniFile.WriteValue("input", "path", this.txtInputPath.Text);
			}
		}

		private void button3_Click(object sender, EventArgs e) {
			FolderBrowserDialog folderBrowser = new FolderBrowserDialog();
			folderBrowser.ShowNewFolderButton = false;
			folderBrowser.Description = "Selecione o diretorio destino";
			DialogResult result = folderBrowser.ShowDialog(this);

			if (result == System.Windows.Forms.DialogResult.OK) {
				this.txtOutputPath.Text = folderBrowser.SelectedPath;
				this.iniFile.WriteValue("output", "path", this.txtOutputPath.Text);
			}
		}

		private void Form1_FormClosed(object sender, FormClosedEventArgs e) {
			this.writeIniFile();
		}

        private void processFiles(string input_path, List<string> file_extensions, string output_path, string output_format) {
            AbstractPrinter printer = getPrinter(output_format, output_path);

            if (printer == null) {
                MessageBox.Show("ERROR: Unknown output_format: " + output_format);
                Application.Exit();
            }

			Parser parser = new Parser();
            List<string> files = getFiles(input_path, file_extensions);


            // input
            parser.parse(files, this.resetProgress, this.updateParserProgress);

            // output
            printer.process(parser, this.resetProgress, this.updateWriterProgress);
		}

        private static List<string> getFiles(string input_path, List<string> file_extensions) {
            string[] encodings = { "utf-8", "iso-8859-1" };
            List<string> files = new List<string>();

            foreach (string ext in file_extensions) {
                files.AddRange(Directory.GetFiles(input_path, "*" + ext, SearchOption.AllDirectories));
            }

            files.Sort();

            return files;
        }

        public void resetProgress(int max) {
            this.progressBar.Value = 0;
            this.progressBar.Maximum = max;
            
            Application.DoEvents();
        }

        public void updateParserProgress(int current) {
            updateProgress("Analisando...", current);
        }

        public void updateWriterProgress(int current) {
            updateProgress("Escrevendo...", current);
        }

        private void updateProgress(string text, int current) {
            this.progressBar.Value = current;
            this.progressLabel.Text = text + " (" + (current + 1) + "/" + this.progressBar.Maximum + ")";

            Application.DoEvents();
        }


        private static AbstractPrinter getPrinter(string output_format, string output_path) {
            AbstractPrinter printer = null;

            if (output_format.ToLower() == "html") {
                printer = new HTMLPrinter(output_path);
            }
            else if (output_format.ToLower() == "wiki") {
                printer = new WikiMarkupPrinter(output_path);
            }

            return printer;
        }

		private void button1_Click(object sender, EventArgs e) {
			this.gbxInput.Enabled = false;
			this.gbxOutput.Enabled = false;
			this.btnProcess.Enabled = false;

			this.processFiles(	this.txtInputPath.Text,
								this.getExtensionList(),
								this.txtOutputPath.Text,
								this.cmbOutputFormat.Text);

			this.gbxInput.Enabled = true;
			this.gbxOutput.Enabled = true;
			this.btnProcess.Enabled = true;

            this.progressBar.Value = 0;
            this.progressLabel.Text = "";

		}

	}
}
